#ifndef DLNA_MANAGER_H
#define DLNA_MANAGER_H

#include <mutex>
#include <string>
#include <vector>
#include <memory>
#include <map>
#include <atomic>

#include "handler.h"
#include "message.h"
#include "dmcApi.h"
#include "cast_engine_common.h"
#include "cast_service_common.h"
#include "wifi_device.h"
#include "system_ability_definition.h"
#include "i_wifi_device_callback.h"
#include "common_event_subscriber.h"
#include "common_event_support.h"
#include "common_event_manager.h"

namespace OHOS {
namespace CastEngine {
namespace CastEngineService {

using namespace OHOS::EventFwk;

class IDlnaManagerListener;
class DlnaCallback;
class CastStateObserver;
class CastStateEventSubscriber;

class DlnaManager : public Handler, public std::enable_shared_from_this<DlnaManager> {
public:
    enum MessageId : int {
        DLNA_MSG_STACK_INIT,
        DLNA_MSG_STACK_DESTROY,
        DLNA_MSG_WIFI_CONNECTED,
        DLNA_MSG_WIFI_DISCONNECTED
    };

    enum DlnaPlaybackStatus { STOPPED, PLAYING };

    static DlnaManager &GetInstance();

    void Init(std::shared_ptr<IDlnaManagerListener> listener);
    void DeInit();

    void StartDiscovery();
    void StopDiscovery();

    void OnDeviceInfoFound(const CastInnerRemoteDevice &newDevice);
    void OnDeviceOffline(unsigned long deviceId);

    std::string GetIpAddr();
    bool AddDeviceMap(const std::string &deviceUuid, uint32_t deviceId);
    std::string GetDeviceUuid(uint32_t dlnaDevId);
    void ClearDevice();

    std::shared_ptr<DlnaCallback> GetDlnaCallback();
    void SetDlnaCallback(std::shared_ptr<DlnaCallback> callback);

    void HandleMessage(const Message &msg) override;

    DlnaPlaybackStatus GetPlaybackStatus() const;
    void SetPlaybackStatus(DlnaPlaybackStatus status);

private:
    DlnaManager();
    ~DlnaManager();
    DlnaManager(const DlnaManager &) = delete;
    DlnaManager &operator=(const DlnaManager &) = delete;

    void StartDlnaApiStackInit();
    int RegisterWifiStatusChangeListener();

    std::shared_ptr<IDlnaManagerListener> GetListener();
    void SetListener(std::shared_ptr<IDlnaManagerListener> listener);
    void ResetListener();
    bool HasListener() const;

    void AddDevice(const CastInnerRemoteDevice &newDevice);
    void RemoveDevice(const std::string &deviceUuid);
    bool HasDevice() const;
    std::vector<CastInnerRemoteDevice> GetDevices() const;

    DlnaDmc::DmcApi dmcApi_;

    mutable std::mutex mutex_;
    std::shared_ptr<IDlnaManagerListener> listener_;
    std::vector<CastInnerRemoteDevice> devices_;
    std::map<std::string, uint32_t> deviceHashMap_;
    std::shared_ptr<DlnaCallback> dlnaCallback_;
    std::atomic<bool> devReportEnable_{false};
    bool isStackInitialized_{false};
    DlnaPlaybackStatus playbackStatus_{STOPPED};
    std::shared_ptr<CastStateObserver> castStateObserver_;
};

class IDlnaManagerListener {
public:
    virtual ~IDlnaManagerListener() = default;
    virtual void OnDeviceFound(const std::vector<CastInnerRemoteDevice> &devices) = 0;
    virtual void OnDeviceOffline(const std::string &deviceUuid) = 0;
};

class DlnaCallback {
public:
    virtual ~DlnaCallback() = default;
    virtual void OnDeviceOffline(unsigned long deviceId) = 0;
};

class CastStateObserver {
public:
    explicit CastStateObserver(DlnaManager* connection);
    ~CastStateObserver();
    void StartEventSubscriber();
    void StopEventSubscriber();

private:
    std::shared_ptr<CastStateEventSubscriber> castSubscriber_;
    DlnaManager* connection_;
};

class CastStateEventSubscriber : public CommonEventSubscriber {
public:
    CastStateEventSubscriber(const CommonEventSubscribeInfo &info, DlnaManager* connection);
    ~CastStateEventSubscriber() = default;
    void OnReceiveEvent(const CommonEventData &data) override;
private:
    DlnaManager* connection_;
};

class WifiCallback : public Wifi::IWifiDeviceCallBack {
public:
    WifiCallback() = default;
    ~WifiCallback() = default;

    void OnWifiStateChanged(int state) override;
    void OnWifiConnectionChanged(int state, const OHOS::Wifi::WifiLinkedInfo &info) override;
    void OnWifiRssiChanged(int rssi) override;
    void OnWifiWpsStateChanged(int state, const std::string &pinCode) override;
    void OnStreamChanged(int direction) override;
    void OnDeviceConfigChanged(Wifi::ConfigChange value) override;
    sptr<IRemoteObject> AsObject() override;
};

} // namespace CastEngineService
} // namespace CastEngine
} // namespace OHOS

#endif // DLNA_MANAGER_H